using System;
using System.Text;
using Com.ContentRendering.Api.ParserEngine.Exceptions;

namespace Com.ContentRendering.Api.ParserEngine.State
{
    /// <summary/>
    internal class ContentState : AbstractState 
    {
        private StringBuilder _stringBuilder;
        
        /// <summary/>
        internal ContentState(AbstractState state) : base(state) 
        {
            this._stringBuilder = new StringBuilder();
        }
                
        /// <summary/>
        internal ContentState(
            DocumentParser documentParser,
            OutputNodeInterface outputNode) 
            :base (
            documentParser,
            outputNode) 
        {
            this._stringBuilder = new StringBuilder();
        }

        /// <summary/>
        protected override void ParseEscapeCharacter()
        {
            // only create a content node if it is not empty
            if (this._stringBuilder.Length != 0)
            {
                base._outputNode.AddContent(this._stringBuilder.ToString());
            }

            // the state needs to be updated
            base._documentParser.State = new EscapeState(this);
        }

        /// <summary/>
        protected override void ParseStartCharacter()
        {
            // only create a content node if it is not empty
            if (this._stringBuilder.Length != 0)
            {
                base._outputNode.AddContent(this._stringBuilder.ToString());
            }

            // the state needs to be updated
            base._documentParser.State = new RootTagState(this);
        }

        /// <summary/>
        protected override void ParseEndCharacter()
        {
            // only create a content node if it is not empty
            if (this._stringBuilder.Length != 0)
            {
                base._outputNode.AddContent(this._stringBuilder.ToString());
            }

            // fetch the parent
            OutputNodeInterface parent = base._outputNode.Parent;

            // if the parent is negative something bad happened
            if (parent == null)
            {
                throw new MissingStartCharacterException();
            }

            // decrease the nested count
            base._outputNode = parent;

            // the state needs to be updated
            base._documentParser.State = new ContentState(this);
        }

        /// <summary/>
        protected override void ParseIfNotCharacter()
        {
            this._stringBuilder.Append(this._documentParser.SpecialCharacters.IfNot);
        }

        /// <summary/>
        protected override void ParseIfCharacter()
        {
            this._stringBuilder.Append(this._documentParser.SpecialCharacters.If);
        }

        /// <summary/>
        protected override void ParseSubstitutionCharacter()
        {
            this._stringBuilder.Append(this._documentParser.SpecialCharacters.Substitution);
        }

        /// <summary/>
        protected override void ParseTransparentCharacter()
        {
            this._stringBuilder.Append(this._documentParser.SpecialCharacters.Transparent);
        }

        /// <summary/>
        protected override void ParseParentCharacter()
        {
            this._stringBuilder.Append(this._documentParser.SpecialCharacters.Parent);
        }

        /// <summary/>
        protected override void ParseChildCharacter()
        {
            this._stringBuilder.Append(this._documentParser.SpecialCharacters.Child);
        }

        /// <summary/>
        protected override void ParseOtherCharacter(char value)
        {
            this._stringBuilder.Append(value);
        }

        /// <summary/>
        protected override void EndHandler()
        {
            // is there any content, if so write it
            if (this._stringBuilder.Length != 0)
            {
                base._outputNode.AddContent(this._stringBuilder.ToString());
            }
        }
    }
}
